﻿using System;
using System.Linq;
using HISModels.Entities;
using HISModels.ViewModel;

namespace HISRestServices.Services {

    public class NumberGenerator {

        #region Fields
        private static NumberGenerator instance = null;
        private static RegistrationNumber regOpdNumber = null;
        private static MedicalRecordNumber medicalRecNumb = null;
        #endregion

        #region Constructors
        private NumberGenerator() {
        }

        public static NumberGenerator Instance {
            get {
                if (instance == null) instance = new NumberGenerator();
                try {
                    Type type = instance.GetType();
                    if (type.Name.ToLower() != "numbergenerator") throw new Exception();
                } catch {
                    instance = null;
                    instance = new NumberGenerator();
                }
                return instance;
            }
        }
        #endregion

        #region Method
        public RegistrationNumber GetNewRegNumber(HISModels.HISContext repo, int HuLoBRelId) {
            regOpdNumber = new RegistrationNumber();
            SysSequenceNumber tSequencenumber = null;
            lock (regOpdNumber) {
                try {
                    DateTime now = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
                    var k = (from a in repo.SysSequenceNumbers
                             join b in repo.HuLobRels on a.HuLobRelId equals b.Id
                             join c in repo.RefHus on b.HospitalUnitId equals c.Id
                             join d in repo.RefLobs on b.LineOffBusinessUnitID equals d.Id
                             where a.TransactionCodeId == 4 && a.HuLobRelId == HuLoBRelId
                             select new {
                                 SysSequenceNumber = a,
                                 LoBCode = d.CodeValue,
                                 HuInitial = c.CodeValue
                             }).First();

                    if (k.SysSequenceNumber.DateValue < now) {
                        k.SysSequenceNumber.DateValue = now;
                        k.SysSequenceNumber.NumberValue = 1;
                    } else {
                        k.SysSequenceNumber.NumberValue = k.SysSequenceNumber.NumberValue + 1;
                    }

                    repo.SaveChanges();

                    regOpdNumber.RegNumber = k.HuInitial + "-" + k.LoBCode + "-" + k.SysSequenceNumber.DateValue.ToString(k.SysSequenceNumber.CodeFormat.Split('-')[0].ToString()) + "-" + k.SysSequenceNumber.NumberValue.ToString(k.SysSequenceNumber.CodeFormat.Split('-')[1].ToString());

                } catch {
                } finally {
                    if (tSequencenumber != null) tSequencenumber = null;
                }
            }
            return regOpdNumber;
        }

        public MedicalRecordNumber GetMedicalRecordNumber(HISModels.HISContext repo, int huId) {
            medicalRecNumb = new MedicalRecordNumber();
            SysSequenceNumber tSequencenumber = null;
            lock (medicalRecNumb) {
                try {
                    DateTime now = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                    var k = (from a in repo.SysSequenceNumbers
                             join b in repo.HuLobRels on a.HuLobRelId equals b.Id
                             join c in repo.RefHus on b.HospitalUnitId equals c.Id
                             join d in repo.RefLobs on b.LineOffBusinessUnitID equals d.Id
                             where a.TransactionCodeId == 3 && c.Id == huId
                             select new {
                                 SysSequenceNumber = a,
                                 HuInitial = c.CodeValue
                             }).First();

                    DateTime dateFromDB = new DateTime(k.SysSequenceNumber.DateValue.Year, k.SysSequenceNumber.DateValue.Month, 1);

                    if (now > dateFromDB) {
                        k.SysSequenceNumber.DateValue = now;
                        k.SysSequenceNumber.NumberValue = 1;
                    } else {
                        k.SysSequenceNumber.NumberValue = k.SysSequenceNumber.NumberValue + 1;
                    }

                    repo.SaveChanges();

                    string[] splitCodeFormat = k.SysSequenceNumber.CodeFormat.Split('-');

                    medicalRecNumb.MRNo = k.HuInitial + "-" + k.SysSequenceNumber.DateValue.ToString(splitCodeFormat[0]) + "-" + k.SysSequenceNumber.NumberValue.ToString(splitCodeFormat[1]);

                } catch {
                } finally {
                    if (tSequencenumber != null) tSequencenumber = null;
                }
            }
            return medicalRecNumb;
        }

        public string GetDoctorCode(HISModels.HISContext repo, string rawcode) {
            string returnValue = string.Empty;
            SysSequenceNumber tSequencenumber = null;
            lock (this) {
                try {
                    DateTime now = DateTime.Now;
                    var k = (from a in repo.SysSequenceNumbers
                             join b in repo.RefDocumentTypes on a.TransactionCodeId equals b.Id
                             where a.TransactionCodeId == 5
                             select a).First();
                    DateTime dateFromDB = new DateTime(k.DateValue.Year, k.DateValue.Month, k.DateValue.Day);
                    if (now > dateFromDB) {
                        k.DateValue = now;
                        k.NumberValue = 1;
                    } else {
                        k.NumberValue = k.NumberValue + 1;
                    }

                    repo.SaveChanges();

                    returnValue = rawcode + k.NumberValue.ToString(k.CodeFormat);
                } catch {
                } finally {
                    if (tSequencenumber != null) tSequencenumber = null;
                }
                
            }
            return returnValue;
        }
        #endregion

    }

}